package planner.plan;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.jdom.Attribute;
import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;

public class PlanOutputter {
//TODO Arrumar metamodelo -> trocar nomes
	
	
	
	private ArrayList<Plan> plans;
	private File file;
	private Document doc;
	private Element root;
	private Namespace xmi;
	private Namespace planns;

	
	public PlanOutputter(String filename){
		file = new File(filename);
		
		plans = new ArrayList<Plan>();
		xmi = Namespace.getNamespace("http://www.omg.org/XMI");
		planns = Namespace.getNamespace("Plan", "Plan");
		
		root = new Element("XMI", xmi);
		root.addNamespaceDeclaration(planns);
		doc = new Document(root);
	}	
	
	
	public void addPlan(Plan p, String name){
		Element planElement = new Element("Plan", planns);
		root.addContent(planElement);
		
		PlanStep lastStep = p.getLastStep();
		ArrayList<PlanStep> parents = lastStep.getPreviousSteps();
		
		while(!parents.isEmpty()){
			ArrayList<PlanStep> gparents = new ArrayList<PlanStep>();
			
			while(!parents.isEmpty()){
				if(!setContainsSpecialStep(parents)){			
					PlanStep step = parents.remove(0);
					Element stepElement = buildStepElement(step);
					planElement.addContent(0, stepElement);
					gparents.addAll(step.getPreviousSteps());
				} else{
					PlanStep step = getSpecialStepFromSet(parents);
					parents.remove(step);					
					gparents.addAll(step.getPreviousSteps());
					planElement.setAttribute("name", step.getOperatorName());
					planElement = new Element("Plan", planns);
					root.addContent(planElement);
					
					if(!parents.isEmpty())
						buildConstructorElement(parents, getClassName(step.getOperatorName()));
					
					parents.clear();
				}
			}
			
			parents.addAll(gparents);
		}
		planElement.setAttribute("name", name);
	}
	
	private PlanStep getSpecialStepFromSet(ArrayList<PlanStep> set){
		Iterator<PlanStep> iStep = set.iterator();
		while (iStep.hasNext()) {
			PlanStep planStep = (PlanStep) iStep.next();
			if(planStep.isSpecialStep())
				return planStep;
		}
		return null;
	}	
	
	private boolean setContainsSpecialStep(ArrayList<PlanStep> previousSteps) {
		Iterator<PlanStep> iPS = previousSteps.iterator();
		while (iPS.hasNext()) {
			PlanStep planStep = (PlanStep) iPS.next();
			if(planStep.isSpecialStep())
				return true;
		}
		
		return false;
	}
	
	private void buildConstructorElement(ArrayList<PlanStep> toConstructor, String className) {
		//TODO arrumar o nome do construtor
		
//		Plan constructor = new Plan();
//		constructor.setOpSequence(toConstructor);
//		addPlan(constructor, "new " + className + " constructor");
		
		
		Element planElement = new Element("Plan", planns);
		planElement.setAttribute(new Attribute("name", "Constructor:" + className));
		root.addContent(planElement);		

		ArrayList<PlanStep> previousSteps = toConstructor;
		Plan p = new Plan();
		
		while(!previousSteps.isEmpty()){			
			
			Iterator<PlanStep> iPreviousStep = previousSteps.iterator();
			ArrayList<PlanStep> aux = new ArrayList<PlanStep>();
			
			while (iPreviousStep.hasNext()) {
				PlanStep planStep = (PlanStep) iPreviousStep.next();
				planElement.addContent(0, buildStepElement(planStep));
				aux.addAll(planStep.getPreviousSteps());
			}			
			
			previousSteps.clear();
			previousSteps.addAll(aux);
		}
	}
	
	private Element buildStepElement(PlanStep ps){
		Element stepElement = new Element("actionSequence", planns);
		stepElement.setAttribute("name", ps.getOperatorName());	
		return stepElement;
	}
	
	public void printFile() throws IOException{		
		XMLOutputter out = new XMLOutputter();
		file.createNewFile();				
		try {
			out.output(doc, new FileOutputStream(file));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private String getClassName(String fullOpName){
		int begin = fullOpName.indexOf(":") + 1;
		int end = fullOpName.lastIndexOf(".");
		if(end < 0)
			end = fullOpName.length();
		
		String className = fullOpName.substring(begin, end);
		return className;
	}
}
